/*
@STI LICENSE
(C) 2006-2008 Universit�t Innsbruck.

This file is part of myOntology.

myOntologyis free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

myOntologyis distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with myOntology.  If not, see <http://www.gnu.org/licenses/>.

@STI LICENSE */
/**
 * 
 */
package org.myontology.model;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.myontology.controller.AttributeHolder;
import org.openrdf.model.URI;
import org.openrdf.model.impl.URIImpl;

/**
 *  @author <a href="michael.hackl@sti2.at">Michael Hackl</a>
 * Project: Myontology - www.myontology.org
 * STI
 */
public class Subject extends Element {

	
	public Subject() {
		
	}
	
	public Subject(URI type) {
		this.type = type;
	}
	
	public static final String NAMEFORMELEMENT = "Entry";
	
	
	protected void init() {
		Field[] f = getClass().getFields();
		for (int i=0;i<f.length;i++) {
			if (f[i].getType().equals(Property.class)) {
				try {
					Property p = (Property) f[i].get(this);
					String name = f[i].getName();
					addProperty(name, p);
				} catch (Exception e) {
					throw new RuntimeException("problem with property: "+f[i].getName()+" in class "+getClass().getName());
				} 
			}
		}
		
	}

	/**
	 * @param name
	 * @param p
	 */
	public void addProperty(String name, Property p) {
		properties.add(p);
		if (p.getPredicate()!=null)
			predicateMap.put(p.getPredicate(), p);
		else {
			value=p;
		}
		p.setKey(name);
		p.setContainer(this);
		keyMap.put(p.getKey(), p);
	}

	public Property retrieveProperty(String key) {
		return keyMap.get(key);
	}
	
	private List<SubjectValidator> validators = new ArrayList<SubjectValidator>();
	private List<Property> properties = new ArrayList<Property>();
	private Map<URI, Property> predicateMap = new HashMap<URI, Property>();
	private Map<String,Property> keyMap = new HashMap<String, Property>();
	private URI type;
	
	public void addValidator(SubjectValidator validator) {
		validators.add(validator);
	}
	
	public List<Property> getProperties() {
		return properties;
	}

	public void setProperties(List<Property> properties) {
		this.properties = properties;
	}

	public Map<URI, Property> getPredicateMap() {
		return predicateMap;
	}

	public void setPredicateMap(Map<URI, Property> predicateMap) {
		this.predicateMap = predicateMap;
	}

	public URI getType() {
		return type;
	}

	public void setType(URI type) {
		this.type = type;
	}
	
	private Property value= new Property(null,"","",Relation.ONE_TO_ONE,Type.LITERAL);;
	public String getId() {
		return value.getValue()==null?"":value.getValue().stringValue();
	}
	public void setValue(String value) {
		this.value.addValue(value);
	}
	public URI getURI() {
		return new URIImpl(getNamespace()+getId());
	}
	
	public String getKey() {
		return getClass().getName();
	}
	
	public void parseAttributes(AttributeHolder attributes) {
		setValue(attributes.getRequestParameter(getKey()));
		for (Iterator<Property> it = properties.iterator();it.hasNext();) {
			Property p = it.next();
			p.addValue(attributes.getRequestParameter(NAMEFORMELEMENT+p.getKey()));
		}
	}
	public List<Exception> validate(AttributeHolder attributes) {
		ArrayList<Exception> exceptions = new ArrayList<Exception>();
		for (Iterator<SubjectValidator> it = validators.iterator();it.hasNext();) {
			try {
				it.next().callCachedValidation(this, attributes);
			}
			catch (Exception e) {
				exceptions.add(e);
			}
		}
		return exceptions;
	}
	
	public boolean isValid(AttributeHolder attributes) {

		if (validate(attributes).size()>0) {

			return false;
		}
		for (Iterator<Property> it = properties.iterator();it.hasNext();) {
			if (it.next().validate(attributes).size()>0)
				return false;
		}
		return true;
	}
	public void cleanValidators() {
		validators = new ArrayList<SubjectValidator>();
	}
}
